package eu.darken.octi.sync.module.syncs.jserver.core

import android.content.Context
import com.gitee.wsl.exception.logTag
import com.gitee.wsl.android.ext.ApplicationInit.application
import com.gitee.wsl.flow.DynamicStateFlow
import com.gitee.wsl.data.store.StoreServer
import com.gitee.wsl.struct.dict.sampleDictionary
import com.squareup.moshi.Moshi
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.plus
import timber.log.Timber


class JServerAccountRepo  constructor(
    private val scope: CoroutineScope,
    dispatcherProvider: CoroutineDispatcher=Dispatchers.Default,
    private val context: Context=application,
    storeServer: StoreServer,
    moshi: Moshi,
) {
    /*@OptIn(ExperimentalStdlibApi::class)
    private val adapterCredentials by lazy { moshi.adapter<JServer.Credentials>() }

    private val Context.dataStore by preferencesDataStore(name = "syncs_jserver_credentials")

    private val dataStore: DataStore<Preferences>
        get() = context.dataStore*/

    private val accoutDir = sampleDictionary<String, JServer.Credentials>(storeServer,"syncs_jserver_credentials")

    private val _accounts = DynamicStateFlow(parentScope = scope + dispatcherProvider) {
        /*dataStore.data.first()
            .asMap()
            .filter {
                if (!it.key.name.startsWith(KEY_PREFIX)) {
                    log(TAG, ERROR) { "Unknown entry: $it" }
                    return@filter false
                }
                if (it.value !is String) {
                    log(TAG, ERROR) { "Unknown data: $it" }
                    return@filter false
                }
                true
            }
            .map { it.value as String }
            .map { adapterCredentials.fromJson(it)!! }
            .toSet()*/
        accoutDir.map().values
    }

    val accounts: Flow<Collection<JServer.Credentials>> = _accounts.flow


    suspend fun add(acc: JServer.Credentials): Boolean {
        Timber.d("add(acc=$acc)" )
        var added = false

        _accounts.updateBlocking {
            if (any { it.accountId == acc.accountId }) {
                Timber.d( "Account $acc is already added" )
                return@updateBlocking this
            }

            added = true

            /*dataStore.edit {
                it[stringPreferencesKey("$KEY_PREFIX.${acc.accountId.id}")] = adapterCredentials.toJson(acc)
            }*/

            accoutDir.put("$KEY_PREFIX.${acc.accountId.id}",acc)

            this + acc
        }
        return added
    }

    suspend fun remove(id: JServer.Credentials.AccountId) {
        Timber.d(  "remove(id=$id)" )
        _accounts.updateBlocking {
            val toRemove = firstOrNull { it.accountId == id }

            if (toRemove == null) {
                Timber.w( "Account $id is unknown")
                return@updateBlocking this
            }

            /*dataStore.edit {
                it.remove(stringPreferencesKey("$KEY_PREFIX.${id.id}"))
            }*/
            accoutDir.delete("$KEY_PREFIX.${id.id}")

            this - toRemove
        }
    }

    companion object {
        private const val KEY_PREFIX = "credentials"
        private val TAG = logTag("Sync", "JServer", "AccountRepo")
    }
}